function onTranslatorListContextMenu(grid, rowIndex, e) {
    e.stopEvent();
    grid.selModel.selectRow(rowIndex);

    var listContextMenu = new Ext.menu.Menu({
    	items: [
    		{
    			iconCls: 'copy',
    			text: _('Copy original to translation field'),
    			handler: function() {
    				r = grid.store.getAt(rowIndex);
    				r.set('translated',r.get('original'));
    			}
    		}
    	]
    });
    
    listContextMenu.showAt(e.getXY());
}

MyDesktop.Translator = Ext.extend(Ext.app.Module, {
	
    init : function(){
        this.launcher = {
            text: _('UI Translator'),
            iconCls:'translator',
            handler : this.createWindow,
            windowId : 'Translator',
            scope: this
        }
    },

    createWindow : function(src){
        var desktop = this.app.getDesktop();
        var winname = src.windowId;
        var win = desktop.getWindow(winname);

        if(!win){
			var cm = new Ext.grid.ColumnModel(
				[
				{
			       header: _("Original string"),
			       dataIndex: 'original',
			       width: 220,
			       renderer: htmlEntitiesRender
			    },{
			       header: _("Previous original string"),
			       dataIndex: 'previous',
			       hidden: true,
			       renderer: htmlEntitiesRender
			    },{
			       header: _("Translation"),
			       dataIndex: 'translated',
			       width: 130,
			       renderer: htmlEntitiesRender,
			       editor: new Ext.form.TextField({
			           allowBlank: true
			       })
			    }
			    ]);

			cm.defaultSortable = true;

			var store = new Ext.data.Store({
				proxy: new Ext.data.HttpProxy({
					url: getMainUrl(),
					method: 'POST'
					}),
					baseParams: {action: 'translator'},
				reader: new Ext.data.JsonReader({
						root: 'results',
						id: 'id'
					},[
						{name: 'original'},
		           		{name: 'translated'},
		           		{name: 'status'},
		           		{name: 'previous'}
					]
					)
					//sortInfo: {field: 'status',direction:'ASC'}
			});

			var view = new Ext.grid.GridView({
				autoFill: true,
   		    	getRowClass : function (row, index) { 
			      var cls = ''; 
			      var data = row.data;
			      if (row.modified==null) {
				      switch (data.status) { 
				         case "0": 
				            cls = 'untranslated-row'; 
				            break; 
				         case "1":
				         	cls = 'fuzzy-row';
				         	break; 
				      } 
			      } else {
						cls = 'modified-row';
			      }
			      return cls; 
			   } 
			});

			var filters = new Ext.ux.grid.GridFilters({
					menuFilterText: _('Filter'),
					filters:[
						{type: 'string',  dataIndex: 'original'},
						{type: 'string',  dataIndex: 'translated'},
						],
					local: true
			});
			
		    var grid = new Ext.grid.EditorGridPanel({
		    	autoExpandColumn: 2,
		        store: store,
		        cm: cm,
		        clicksToEdit:1,
		        selModel: new Ext.grid.RowSelectionModel(),
		        view: view,
		        plugins: filters,
		        tbar: [
			        {
			            text: _('Save'),
			            iconCls: 'save',
			            handler : function(){
			                //store.commitChanges();
			                var records = store.getModifiedRecords();
							if (records.length>0) {
							  	var ids = [];
							  	var values =[];
							  	for(i = 0; i< records.length; i++){
									ids.push(records[i].id);
									values.push(records[i].data.translated);
									records[i].data.status = "2";
									records[i].commit(true);
							  	}
								
							  	var util = new Verbum.Utilities();
								util.request({
									el: grid.getEl(),
									msg: _('Saving...'),
						            params: { 
						               action: "translator", 
						               ids: Ext.encode(ids),
						               values: Ext.encode(values),
						               op: 'save'
						              }											
								});
								
								util.on({
									'done': function() {
										view.refresh();	
									}
								})								
							} else {
								console.log("nothing to do");
							}
						  			
			            }
			        },'-',
					{
						xtype:'button',
						tooltip: _('Refresh'),
						iconCls: "x-tbar-loading",
						handler: function() {
							store.reload();	
						}
					}			        
		        ],
				bbar: new Ext.StatusBar({
		            text: _('Some changes will require refresh the page.')
	        	})
	        });
	        
	        grid.on('rowcontextmenu', onTranslatorListContextMenu);
			/*
	        grid.on({
	        	'beforeedit': {
					fn: function(e) {
						var str = e.value;
						e.value = str.replace(/&lt;/g, "<").replace(/&gt;/g, ">")
					}
				},
				'validateedit': {
					fn: function(e) {
						var str = e.value;
						e.value = str.replace(/</g,"&lt;").replace(/>/g,"&gt;");
					}
				}
	        });
	        */
			store.on({
			/*
				'update': {
					fn: function(store,record,op) {
						if (Ext.data.Record.COMMIT==op) {
							record.data.status = "2";
							Verbum.Util.request({
					            params: { 
					               action: "translator", 
					               id: record.id,
					               value: record.data.translated,
					               op: 'save'
					              }											
							});
							view.refresh();
						}
					}
				},*/
				'loadexception': function(obj,opt,response,e) {
					res = Ext.util.JSON.decode(response.responseText);
					Ext.Msg.error(res.error);
				}
			});
			
            win = desktop.createWindow({
				id: winname,
				title: src.text,
				closable:true,
				width:600,
				height:400,
				plain:true,
				layout: 'fit',
				iconCls: src.iconCls,
				items: grid
            });

            store.load();
        }
        win.show();
    },
	display : function(){
        this.createWindow();
	}
});
